#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>

#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/sysmacros.h>

#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>

// 拷贝普通文件
void copyfile(FILE *fp1, FILE *fp2)
{
    char *buf = calloc(1, 1024*1024);
    while(1)
    {
        int n = fread(buf, 1, 1024*1024, fp1);
        if(n < 1024*1024)
        {
            if(ferror(fp1))
            {
                perror("读取文件失败");
                exit(0);
            }
        }
        if(n == 0)
            break;
        fwrite(buf, 1, n, fp2);
    }
    free(buf);
}

void copydir(const char *srcpath, const char *dstpath)
{
    DIR *dp = opendir(srcpath);

    struct dirent *ep;
    while(1)
    {
        ep = readdir(dp);
        
        if(ep == NULL)
            break;

        // 切换到源目录下读取各文件属性
        chdir(srcpath);
        struct stat finfo;
        stat(ep->d_name, &finfo);

        if(S_ISREG(finfo.st_mode))
        {
            FILE *fp1 = fopen(ep->d_name, "r");

            // 切换到目标目录下
            mkdir(dstpath);
            chdir(dstpath);
            FILE *fp2 = fopen(ep->d_name, "w");

            copyfile(fp1, fp2); // 很轻松
            fclose(fp1);
            fclose(fp2);
        }
    }
}

int main(int argc, char const *argv[]) // a.out /etc/xxx/a  ../yyy/b
{
    if(argc != 3)
    {
        printf("请指定源文件、目标文件\n");
        exit(0);
    }

    struct stat finfo;
    stat(argv[1], &finfo);

    if(S_ISDIR(finfo.st_mode))
    {
        // 将当前路径、要拷贝的原目录、目标绝对路径
        char oripath[100];
        char srcpath[100];
        char dstpath[100];

        getcwd(oripath, 100); // 获取起始路径

        chdir(argv[1]);       // 切换到源目录
        getcwd(srcpath, 100); // 获取源目录路径

        chdir(oripath);       // 切换到起始路径
        chdir(argv[2]);       // 切换到目标目录
        getcwd(dstpath, 100); // 获取目录目录路径

        copydir(srcpath, dstpath);
    }
    else if(S_ISREG(finfo.st_mode))
    {
        FILE *fp1 = fopen(argv[1], "r");
        FILE *fp2 = fopen(argv[2], "w");
        copyfile(fp1, fp2);
        fclose(fp1);
        fclose(fp2);
    }
    else
    {
        printf("非法文件，无法拷贝，再见！\n");
        exit(0);
    }

    return 0;
}
